home *** CD-ROM | disk | FTP | other *** search
- /* CEAppManager.m
- *
- * This is the basic controller of the App. It manages all big abstraction
- * tasks for the panels, documents and connections to the outside.
- *
- * For interface-info see the header file. The comments in this file mostly
- * cover only the real implementation details.
- *
- * Written by: Thomas Engel
- * Created: 23.10.1993 (Copyleft)
- * Last modified: 07.05.1994
- */
-
- #import <CEAppManager.h>
- #import <CEClassEditor.h>
- #import <CEListener.h>
- #import <CEInfo.h>
- #import <Text_MiscExtensions.h>
- #import <MiscEmacsText.h>
- #import <MiscCompletionText.h>
-
- #import <misckit/misckit.h>
-
- @implementation CEAppManager
-
- - appWillInit:sender
- {
- // This is the init part we need to pass before we get the messages that
- // we have to open some files.
- // To be able to init a class we need the have the Preferences,
-
- // preferences = [CEPreferencesManager new];
-
- // Now lets load the docu templates
-
- NXStream * aStream;
- id aPath;
- id ourListener;
-
- // Setup out own Listener...this is really nasty..anyway.
-
- [[NXApp appListener] free];
-
- ourListener = [[CEListener alloc] init];
- [ourListener setDelegate:self];
- [ourListener checkInAs:[NXApp appName]];
- [ourListener addPort];
-
- [NXApp setAppListener:ourListener];
-
- // Well now this is a litle rough....maybe we should search for those files
- // inside the ~/AppInfo or even *Library/ClassEditor sections..anyway.
-
- aPath = [MiscString newWithString:
- [(NXBundle *)[NXBundle mainBundle] directory]];
- [aPath cat:"/CEClassDocuTemplate.rtf"];
- if( [aPath doesExistInFileSystem] )
- {
- aStream = NXMapFile( [aPath stringValue], NX_READONLY );
- [classDocTemplateView readRichText:aStream];
- NXCloseMemory( aStream, NX_FREEBUFFER );
- }
- [aPath free];
-
- aPath = [MiscString newWithString:
- [(NXBundle *)[NXBundle mainBundle] directory]];
- [aPath cat:"/CEMethodDocuTemplate.rtf"];
- if( [aPath doesExistInFileSystem] )
- {
- aStream = NXMapFile( [aPath stringValue], NX_READONLY );
- [methodDocuTemplateView readRichText:aStream];
- NXCloseMemory( aStream, NX_FREEBUFFER );
- }
- [aPath free];
-
- // Here comes the hack...
-
- // [MiscCompletionText poseAs:[Text class]];
- [MiscEmacsText poseAs:[Text class]];
-
- // Let's see if we have the necessary defaults at hand !
- // Either hardcode them...or adjust them with a DefaultsEditor
-
- if( ![NXApp knowsDefaultValue:"HeaderDirectories"] )
- [NXApp setDefault:"HeaderDirectories"
- to:".\t"\
- "~/Developer/Headers\t"\
- "/LocalDeveloper/Headers\t"\
- "/LocalDeveloper/Headers/misckit\t"\
- "/NextDeveloper/Headers/appkit\t"\
- "/NextDeveloper/Headers/foundation\t"\
- "/NextDeveloper/Headers/eoaccess\t"\
- "/NextDeveloper/Headers/eointerface\t"\
- "/NextDeveloper/Headers/3Dkit\t"\
- "/NextDeveloper/Headers/indexing\t"\
- "/NextDeveloper/Headers/eoaccess\t"\
- "/NextDeveloper/Headers/nikit\t"\
- "/NextDeveloper/Headers/remote\t"\
- "/NextDeveloper/Headers/dbkit\t"\
- "/NextDeveloper/Headers/soundkit"];
-
-
- // NOTE: We might use the source pathes for header search too. Should
- // take a look at it some day..
-
- if( ![NXApp knowsDefaultValue:"SourceDirectories"] )
- [NXApp setDefault:"SourceDirectories"
- to:".\t"\
- "~/Developer"];
-
- if( ![NXApp knowsDefaultValue:"DocumentationDirectories"] )
- [NXApp setDefault:"DocumentationDirectories"
- to:".\t"\
- "./Documentation\t"\
- "/LocalDeveloper/Documentation/MiscKit\t"\
- "/NextLibrary/Documentation/NextDev/GeneralRef/02_ApplicationKit"];
-
- // Here we will write down the defaults which show the ASCII prettyprinting
- // This DEFINITLY is stupid..it should be customizable.
-
- [NXApp setDefault:"text0" to:"Helvetica \\fs24 \\red0\\green0\\blue0 \\ul0"];
- [NXApp setDefault:"text1" to:"Helvetica-Bold \\fs24 \\red0\\green0\\blue0 \\ul0"];
- [NXApp setDefault:"text2" to:"Times-Bold \\fs28 \\red0\\green0\\blue0 \\ul0"];
- [NXApp setDefault:"text3" to:"Helvetica \\fs24 \\red85\\green85\\blue85 \\ul0"];
- [NXApp setDefault:"text4" to:"Ohlfs \\fs20 \\red4\\green8\\blue114 \\ul0"];
- [NXApp setDefault:"text5" to:"Courier-Bold \\fs24 \\red0\\green0\\blue0 \\ul0"];
- [NXApp setDefault:"text6" to:"Ohlfs \\fs20 \\red0\\green0\\blue0 \\ul0"];
-
- // Now lets get all the Prefs into the real objects
-
- [self _readPreferences];
- return self;
- }
-
- - appDidInit:sender
- {
- // This is some kind of late init. These object are need for working but
- // not for reading the classes or having a class initialized.
-
-
- return self;
- }
-
- - (int)app:sender openFile:(const char *)path type:(const char *)type
- {
- // This method is performed whenever a user opens a document from the
- // Workspace Manager.
- // We use our default file open method with some default params.
-
- return [self openFile:path onHost:"*" atTrueLine:0];
- }
-
- - (BOOL)appAcceptsAnotherFile:sender
- {
- // Inform the workspace that we can open multiple files.
- return YES;
- }
-
- - appDidBecomeActive:sender
- {
- return self;
- }
-
- - appWillTerminate:sender
- {
- // Now lets see what we have...ask every window what is going on.
-
- BOOL ready;
- int i;
- id windowList;
- int count;
- int result;
-
- windowList = [NXApp windowList];
- count = 0;
-
- for( i=0; i<[windowList count]; i++ )
- if( [[windowList objectAt:i] isDocEdited] ) count++;
-
- // Well if there are windows with unsaved contents we should tell the
- // user about it.
- // We won't leave until the user has decided what to do on the top level.
-
- if( count == 0 ) return self;
-
- ready = NO;
- while( !ready )
- {
- result = NXRunAlertPanel( "Quit", "There are edited windows.",
- "Review Unsaved", "Quit Anyway", "Cancel" );
-
- if( result == NX_ALERTOTHER )
- return nil;
-
- else if( result == NX_ALERTDEFAULT )
- ready = [self _closeAllWindows];
-
- else ready = YES;
- }
- return self;
- }
-
- - (BOOL)_closeAllWindows
- {
- // We will try to close all windows and if we succeed we will let the app
- // know. YES = all closed
- // NOTE: Well this is kind of ugly because the app should maintain a list
- // of all the controllers that are responsible for some data. But I
- // don't want to hack down another list access stuff. So we do it
- // this way. Maybe in the future I will change that.
-
- id delegateList;
- id aDelegate;
- int i;
- id windowList;
- BOOL success;
-
- windowList = [NXApp windowList];
- delegateList = [List new];
-
- // Lets find all the delegates first.
-
- for( i=0; i<[windowList count]; i++ )
- {
- aDelegate = [[windowList objectAt:i] delegate];
- if( aDelegate != nil &&
- [aDelegate isKindOf:[CEClassEditor class]] )
- [delegateList addObjectIfAbsent:aDelegate];
- }
- success = YES;
-
- for( i=0; i<[delegateList count]; i++ )
- {
- if( [[delegateList objectAt:i] close:self] == nil )
- {
- success = NO;
- break;
- }
- }
-
- return success;
- }
-
- - addToReleasePool:anObject
- {
- return [NXApp delayedFree:anObject];
- }
-
- - (int)openFile:(char *)path onHost:(char *)host atTrueLine:(int *)line;
- {
- // This method is performed whenever a user opens a document.
- // It takes care that every file is only opened once.
-
- id newEditor;
- id aString;
- id basename;
- id filetype;
- id thePath;
- id windowList;
- id aDelegate;
- int i;
- BOOL loadIt;
-
- // First we have to check if we already know this file !
- // Some window delegate should have the same filename (without .h or .m)
- // Using the window list might not be the safest way..but I guess it
- // will work.
-
- aString = [MiscString newWithString:path];
- filetype = [aString fileExtension];
- newEditor = nil;
-
- if( [filetype cmp:"m"] != 0 &&
- [filetype cmp:"h"] != 0 &&
- [filetype cmp:"rtf"] != 0 )
- {
- // Looks like this is no valid file !
-
- [aString free];
- [filetype free];
- return -1;
- }
- // Now that it is clear that this is a valid file...
-
- [NXApp activateSelf:NO];
-
- windowList = [NXApp windowList];
- basename = [aString fileBasename];
- thePath = [aString pathName];
- [thePath addChar:[MiscString pathSeparator]];
- [thePath concatenate:basename];
- [basename free];
- [aString free];
- loadIt = YES;
-
- for( i=0; i<[windowList count]; i++ )
- {
- aDelegate = [[windowList objectAt:i] delegate];
-
- if( [aDelegate respondsTo:@selector(filename)] &&
- aDelegate != nil )
- {
- if( [thePath cmp:[aDelegate filename]] == 0 )
- {
- // Looks like we have found a delegate that belongs to exactly
- // the same path.
- // We must to ask this delegate now what window we should top.
-
- // If we have to open at a certain line will will skip that.
- // opening at a line will currently bring the cheat window to
- // front anyway...this prevents window cluttter.
-
- if( line == 0 )
- [[aDelegate window] makeKeyAndOrderFront:self];
- loadIt = NO;
-
- // If we have to open at a certain line we should remember
- // who is controlling that window.
-
- newEditor = aDelegate;
- }
- }
- }
- [thePath free];
-
- // If we really have a new editor...let the world know about it.
-
- if( loadIt )
- {
- newEditor = [[CEClassEditor alloc] initFromFile:path];
- if( !newEditor )
- {
- [filetype free];
- return NO;
- }
- }
-
- // Now lets see..do we have to select a certain line ?
- // If there is on ask the editor to do so.
-
- if( line > 0 )
- {
- if( [filetype cmp:"m"] == 0 )
- [newEditor selectTrueLine:(int)line inSource:YES];
- else if( [filetype cmp:"h"] == 0 )
- [newEditor selectTrueLine:(int)line inSource:NO];
- }
- [filetype free];
- return YES;
- }
-
- - showInfo:sender
- {
- if( !info ) info = [CEInfo new];
-
- [info makeKeyAndOrderFront:self];
- return self;
- }
-
- - sendSuggestion:sender
- {
- id mailer;
- id tomiAdr;
- id subject;
- id theText;
-
- tomiAdr = [MiscString newWithString:
- "tsengel@cip.informatik.uni-erlangen.de"];
- subject = [MiscString newWithString:
- "ClassEditor v0.4 suggestion"];
- theText = [MiscString newWithString:
- "Here is a little suggestion on ClassEditor v0.4:\n"];
-
- mailer = [MiscMailApp localMailer];
- [mailer setNoclutter:NO];
- [mailer sendMailTo:tomiAdr subject:subject body:theText];
-
- [theText free];
- [tomiAdr free];
- [subject free];
-
- return self;
- }
-
- - showAccessHelper:sender
- {
- [accessHelper makeKeyAndOrderFront:self];
- return self;
- }
-
- - showPreferences:sender
- {
- // if( preferences ) [preferences makeKeyAndOrderFront:self];
- return self;
- }
-
- - preferences
- {
- return self;
- }
-
- - _readPreferences
- {
- id aString;
- id someString;
- id aList;
- int i;
-
- aString = [MiscString newWithString:
- [NXApp defaultValue:"HeaderDirectories"]];
- headerSearchPathes = [aString tokenize:"\t" into:nil];
-
- [aString setStringValue:[NXApp defaultValue:"SourceDirectories"]];
- sourceSearchPathes = [aString tokenize:"\t" into:nil];
-
- // We will check the paths plus path/Classes path/Categories and
- // path/Protocols
-
- [aString setStringValue:[NXApp defaultValue:"DocumentationDirectories"]];
- aList = [aString tokenize:"\t" into:nil];
- [aString free];
-
- docuSearchPathes = [List new];
-
- for( i=0; i<[aList count]; i++ )
- {
- aString = [[aList objectAt:i] copy];
- [docuSearchPathes addObject:aString];
-
- someString = [aString copy];
- [someString cat:"/Classes"];
- [docuSearchPathes addObject:someString];
-
- someString = [aString copy];
- [someString cat:"/Categories"];
- [docuSearchPathes addObject:someString];
-
- someString = [aString copy];
- [someString cat:"/Protocols"];
- [docuSearchPathes addObject:someString];
- }
- [[aList freeObjects] free];
-
- return self;
- }
-
- - headerSearchPaths
- {
- return headerSearchPathes;
- }
-
- - sourceSearchPaths
- {
- return sourceSearchPathes;
- }
-
- - documentationSearchPaths
- {
- return docuSearchPathes;
- }
-
- - open:sender
- {
- id openPanel;
- char fullName[MAXPATHLEN];
- const char *const *files;
- const char *const fileType[6] = { "m",
- "h",
- NULL};
-
- openPanel = [[OpenPanel new] allowMultipleFiles:YES];
-
- // Run the open panel, filtering for our type of documents
- // We try to open every file the panel returns.
-
- if( [openPanel runModalForTypes:fileType] )
- {
- files = [openPanel filenames];
- for( files = [openPanel filenames]; files && *files; files++)
- {
- // Now lets merge the fullFilename from the directory and the
- // current filename and try to init a editor from this file.
- // We use the default open method with some default params.
-
- sprintf( fullName, "%s/%s",
- [(OpenPanel *)openPanel directory], *files );
- [self openFile:fullName onHost:"*" atTrueLine:0];
- }
- }
- return self;
- }
-
- - new:sender
- {
- [CEClassEditor new];
- return self;
- }
-
- - save:sender
- {
- // [[NXApp keyWindow] save:sender];
- //
- // This is a posible solution
- // But we currently work with a firstResponder solution
-
- return self;
- }
-
- - saveAs:sender
- {
- return self;
- }
-
- - saveTo:sender
- {
- return self;
- }
-
- - saveAll:sender
- {
- return self;
- }
-
- - revert:sender
- {
- return self;
- }
-
- - close:sender
- {
- return self;
- }
-
- - print:sender
- {
- return self;
- }
-
- - setTextFontStyle:sender
- {
- [self _setSelectionFont:textFontField andColor:textFontColorWell];
- return self;
- }
-
- - setMethodNameFontStyle:sender
- {
- [self _setSelectionFont:methodNameField andColor:methodNameColorWell];
- return self;
- }
-
- - setParameterFontStyle:sender
- {
- id firstResponder = [[NXApp mainWindow] firstResponder];
-
- if( [firstResponder respondsTo:@selector(setSelFont:)] )
- [firstResponder setSelFont:[Font newFont:"Times-Italic" size:14]];
- return self;
- }
-
- - setMathSymbolFontStyle:sender
- {
- id firstResponder = [[NXApp mainWindow] firstResponder];
-
- if( [firstResponder respondsTo:@selector(setSelFont:)] )
- [firstResponder setSelFont:[Font newFont:"Symbol" size:14]];
- return self;
- }
-
- - setHeadlinesFontStyle:sender
- {
- [self _setSelectionFont:headlinesFontField
- andColor:headlinesFontColorWell];
- return self;
- }
-
- - setExampleCodeFontStyle:sender
- {
- [self _setSelectionFont:exampleCodeFontField
- andColor:exampleCodeFontColorWell];
- return self;
- }
-
- - setBlankLinesFontStyle:sender
- {
- [self _setSelectionFont:blankLinesFontField
- andColor:blankLinesFontColorWell];
- return self;
- }
-
- - setSourceFontStyle:sender
- {
- [self _setSelectionFont:sourceFontField andColor:sourceFontColorWell];
- return self;
- }
-
- - setKeywordsFontStyle:sender
- {
- [self _setSelectionFont:keywordsFontField andColor:keywordsFontColorWell];
- return self;
- }
-
- - setTypecastFontStyle:sender
- {
- [self _setSelectionFont:typecastFontField andColor:typecastFontColorWell];
- return self;
- }
-
- - setRemarkFontStyle:sender
- {
- [self _setSelectionFont:remarkFontField andColor:remarkFontColorWell];
- return self;
- }
-
- - setBugNoteFontStyle:sender
- {
- [self _setSelectionFont:bugNoteFontField andColor:bugNoteFontColorWell];
- return self;
- }
-
- - _setSelectionFont:aFont andColor:aColor
- {
- // Well this is a lie...we don't get the font but the TextField that has
- // the right font set !!
-
- id firstResponder = [[NXApp mainWindow] firstResponder];
-
- if( [firstResponder respondsTo:@selector(setSelFont:)] &&
- aFont != nil )
- [firstResponder setSelFont:[aFont font]];
- if( [firstResponder respondsTo:@selector(setSelColor:)] &&
- aColor != nil )
- [firstResponder setSelColor:[aColor color]];
-
- // This is for letting the delegates know about the changes to
- // be able to track document modification.
- // The first responder must know about the window because the
- // textDidChange might require it.
-
- if( [firstResponder respondsTo:@selector(window)] )
- [[[NXApp mainWindow] delegate] textDidChange:firstResponder];
-
- return self;
- }
-
- - copyClassDocuTemplate
- {
- // All we do here is to copy the docu template to the pasteboard.
-
- [classDocTemplateView selectAll:self];
- [classDocTemplateView copyTo:[Pasteboard newName:"CETempPb"]];
- return self;
- }
-
- - copyMethodDocuTemplate
- {
- // All we do here is to copy the method template to the pasteboard.
-
- [methodDocuTemplateView selectAll:self];
- [methodDocuTemplateView copyTo:[Pasteboard newName:"CETempPb"]];
- return self;
- }
-
- - windowDidBecomeKey:sender
- {
- // now if our Docu window will become key...we should load the text into
- // it if we havn't yet.
-
- NXStream * aStream;
- id aPath;
-
- if( sender != docuTemplateWindow ) return self;
-
- if( [docuTemplateTextView textLength] < 10 )
- {
- aPath = [MiscString newWithString:
- [(NXBundle *)[NXBundle mainBundle] directory]];
- [aPath cat:"/DocuTemplate.rtf"];
- if( [aPath doesExistInFileSystem] )
- {
- aStream = NXMapFile( [aPath stringValue], NX_READONLY );
- [docuTemplateTextView readRichText:aStream];
- NXCloseMemory( aStream, NX_FREEBUFFER );
- }
- [aPath free];
- }
- return self;
- }
-
- @end
-
- /*
- * History: 13.01.95 Bla.
- *
- *
- * Bugs: No bugs and birds seen....
- */